package com.rzx.websocket;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.rzx.mapper.MessageMapper;
import com.rzx.po.Message;
import com.rzx.service.LoginService;
import com.rzx.web.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Socket处理器
 */
@Slf4j
@Component
public class MyWebSocketHandler extends AbstractWebSocketHandler {

    public static Map<Long, WebSocketSession> userSocketSessionMap = null;
    @Autowired
    LoginService loginService;

    @Autowired
    MessageMapper messageMapper;

    @Autowired
    FileUtil fileUtil;

    static {
        userSocketSessionMap = new HashMap<>();
    }

    /**
     * 建立连接后,把登录用户的id写入WebSocketSession
     */
    public void afterConnectionEstablished(WebSocketSession session)
            throws Exception {
        Object o = session.getAttributes().get("uid");
        if (o == null) return;
        Long uid = Long.valueOf(o.toString());
        String username = loginService.getNameById(uid);
        if (userSocketSessionMap.get(uid) == null) {
            userSocketSessionMap.put(uid, session);
            Message msg = new Message();
            msg.setFrom(uid);
            msg.setTo(Message.ONLINE);
            msg.setFromName(username);
            msg.setText(username + "上线了");
            msg.setDate(new Date());
            messageMapper.insert(msg);
            this.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy年MM月dd日 HH:mm").create().toJson(msg)));
        }
    }

    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        if (message.getPayloadLength() == 0)
            return;

        Message msg = new Gson().fromJson(message.getPayload(), Message.class);
        msg.setDate(new Date());

        if (msg != null) {
            messageMapper.insert(msg);
        }
        this.sendText(msg.getTo(), msg);

    }

    /**
     * 消息传输错误处理
     */
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        removeSession(session);
    }

    /**
     * 关闭连接后
     */
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        log.debug("Websocket:" + session.getId() + "已经关闭");
        removeSession(session);
    }

    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 给所有在线用户发送消息
     *
     * @param message
     * @throws IOException
     */
    public void broadcast(final TextMessage message) throws IOException {
        Iterator<Entry<Long, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
        while (it.hasNext()) {
            final WebSocketSession session = it.next().getValue();
            if (session.isOpen()) {
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            if (session.isOpen()) {
                                session.sendMessage(message);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }

    private void removeSession(WebSocketSession session) throws IOException {
        Iterator<Entry<Long, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
        // 移除当前用户的Socket会话
        while (it.hasNext()) {
            Entry<Long, WebSocketSession> entry = it.next();
            if (entry.getValue().getId().equals(session.getId())) {
                userSocketSessionMap.remove(entry.getKey());
                log.debug("Socket会话已经移除:用户ID" + entry.getKey());
                String username = loginService.getNameById(entry.getKey());
                Message msg = new Message();
                msg.setFrom(entry.getKey());
                msg.setTo(Message.OFFLINE);
                msg.setFromName(username);
                msg.setText(username + "下线了");
                msg.setDate(new Date());
                messageMapper.insert(msg);
                this.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy年MM月dd日 HH:mm").create().toJson(msg)));
                break;
            }
        }
    }

    /**
     * 给某个用户发送消息
     *
     * @param uid
     * @param message
     * @throws IOException
     */
    private void sendText(Long uid, Message message) throws IOException {
        WebSocketSession session = userSocketSessionMap.get(uid);
        if (session != null && session.isOpen()) {
            session.sendMessage(new TextMessage(new GsonBuilder().setDateFormat("yyyy年MM月dd日 HH:mm").create().toJson(message)));
        }
    }

    public void sendFile(Long uid, Message message, byte [] bytes) throws IOException {
        this.sendText(uid, message);
        /*WebSocketSession session = userSocketSessionMap.get(uid);
        try {
            if (bytes != null) {
                BinaryMessage byteMessage = new BinaryMessage(bytes);
                session.sendMessage(byteMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/
    }

}
